package com.qidian.tcba.oss.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.qidian.tcba.oss.dao.AttachmentsMapper;
import com.qidian.tcba.oss.model.Attachment;
import com.qidian.tcba.oss.model.dto.AttachmentResultDTO;
import com.qidian.tcba.oss.service.AttachmentsService;
import com.qidian.tcba.utils.BeanMapper;
import com.qidian.tcba.utils.BusinessException;
import com.qidian.tcba.utils.Message;
import com.qidian.tcba.utils.TablesName;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:fyl
 * @date 2021/7/14 9:53
 * @Modified By:
 * @Modified Date:
 * @Description:
 */


@Service
public class AttachmentsServiceImpl implements AttachmentsService {
    private final AttachmentsMapper attachmentMapper;

    public AttachmentsServiceImpl(AttachmentsMapper attachmentMapper) {
        this.attachmentMapper = attachmentMapper;
    }


    /**
     * 获取表名
     *
     * @param ownerType
     * @return
     */
    public String getOwnerName(int ownerType) {
        String ownerName = "";
        switch (ownerType) {
            case 0:
                ownerName = TablesName.PARK_LOT_RECORD_TASK_NAME;
                break;
            case 1:
                ownerName = TablesName.PARK_LOT_RECORD_PROCESS_HISTORY;
                break;
            case 2:
                ownerName = TablesName.PARK_LOT_RECORD_ASSIGN_TASK_ITEM;
                break;
            case 3:
                ownerName = TablesName.USER_EXTEND_MSG;
                break;
            case 4:
                ownerName = TablesName.PARK_LOT_RECORD_ASSIGN_TASK;
                break;
        }
        return ownerName;
    }

    @Override
    public AttachmentResultDTO upload(MultipartFile file, int ownerType, int ownerId, int businessType) throws IOException {
        String ownerName = getOwnerName(ownerType);
        Attachment attachment = attachBuilder(file, ownerName, ownerId, businessType);
        int insert = attachmentMapper.insert(attachment);
        if (insert != 1) {
            throw new BusinessException(new Message("DB.ADD_FAILED", "设备照片"));
        }
        Attachment attachmentByPath = attachmentMapper.getAttachmentByPath(attachment.getPath());
        attachment.setId(attachmentByPath.getId());
        return BeanMapper.map(attachment, AttachmentResultDTO.class);
    }

    @Override
    public List<AttachmentResultDTO> uploadBatch(MultipartFile[] files, int ownerType, int ownerId, int businessType) {
        String ownerName = getOwnerName(ownerType);
        List<Attachment> attaches = new ArrayList<>();
        for (MultipartFile file : files) {
            Attachment attach = attachBuilder(file, ownerName, ownerId, businessType);
            attaches.add(attach);
        }
        int rows = attachmentMapper.insertAttachments(attaches);
        for (Attachment attach : attaches) {
            Attachment attachmentByPath = attachmentMapper.getAttachmentByPath(attach.getPath());
            attach.setId(attachmentByPath.getId());
        }
        return BeanMapper.mapList(attaches, AttachmentResultDTO.class);
    }

    

    @Override
    public int relateAttach(Integer ownerId, String ownerType, List<Integer> ids) {
        return attachmentMapper.relateAttach(ownerId, ownerType, ids);
    }

    @Override
    public List<AttachmentResultDTO> findByOwner(String ownerType, int ownerId, int businessType) {
        List<Attachment> attachments = attachmentMapper.findByOwnerAndBusinessType(ownerType, ownerId, businessType);
        return BeanMapper.mapList(attachments, AttachmentResultDTO.class);
    }

    @Override
    public int removeByOwner(Integer ownerId, String ownerName, String category) {
        return 0;
    }

    @Override
    public List<String> getPath(int ownerType, int ownerId, int businessType) {
        String ownerName = getOwnerName(ownerType);
        List<Attachment> attachments = attachmentMapper.findByOwnerAndBusinessType(ownerName, ownerId, businessType);
        return attachments.stream().map(Attachment::getPath).collect(Collectors.toList());
    }

    @Override
    public boolean removeById(Integer id) {
        //删除oss文件
        Attachment attachment = attachmentMapper.selectByPrimaryKey(id);
        deleteOssFile(attachment.getObjName());
        //删除数据库记录
        return attachmentMapper.deleteByPrimaryKey(id) == 1;
    }

    /**
     * 下载文件
     *
     * @param objectName
     * @param pathName
     * @return
     */
    private boolean downloadFile(String objectName, String pathName) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = AttachProperties.END_POINT;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = AttachProperties.ACCESS_KEY_ID;
        String accessKeySecret = AttachProperties.ACCESS_KEY_SECRET;
        String bucketName = AttachProperties.BUCKET_NAME;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
        // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));

        // 关闭OSSClient。
        ossClient.shutdown();
        return true;
    }

    /**
     * 删除单个文件
     *
     * @param objectName
     * @return
     */
    private void deleteOssFile(String objectName) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = AttachProperties.END_POINT;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = AttachProperties.ACCESS_KEY_ID;
        String accessKeySecret = AttachProperties.ACCESS_KEY_SECRET;
        String bucketName = AttachProperties.BUCKET_NAME;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        // 删除文件或目录。如果要删除目录，目录必须为空。
        ossClient.deleteObject(bucketName, objectName);

        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    private Map<String, String> uploadOssFile(MultipartFile file) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = AttachProperties.END_POINT;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = AttachProperties.ACCESS_KEY_ID;
        String accessKeySecret = AttachProperties.ACCESS_KEY_SECRET;
        String bucketName = AttachProperties.BUCKET_NAME;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        String date = new DateTime().toString("yyyy/MM/dd");
        //唯一不重复id
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //yyyy/MM/dd/uuid+文件的原始名字
        String name = date + "/" + uuid + file.getOriginalFilename();
        //文件输入流
        InputStream inputStream = null;

        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, name, inputStream);
        // 上传文件。
        ossClient.putObject(putObjectRequest);

        // 关闭OSSClient。
        ossClient.shutdown();
        Map<String, String> map = new HashMap<>();
        map.put("path", "https://" + bucketName + "." + endpoint + "/" + name);
        map.put("objName", name);
        return map;
    }

    private Attachment attachBuilder(MultipartFile file, String ownerType, int ownerId, int businessType) {
        Map<String, String> map = uploadOssFile(file);
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        return new Attachment(
                ownerType,
                ownerId,
                originalFilename,
                map.get("objName"),
                map.get("path"),
                originalFilename.substring(originalFilename.lastIndexOf(".") + 1),
                file.getSize(),
                businessType);
    }
}
